﻿using UnityEngine;
using System.Collections.Generic;

namespace Jinndev {

    // Tile方向
    public static class Direction {

        public const int NONE = -1;

        // 垂直水平
        public const int UP = 0;        // 上
        public const int RIGHT = 1;     // 右
        public const int DOWN = 2;      // 下
        public const int LEFT = 3;      // 左

        // 逆时针
        public const int UP_LEFT = 4;       // 上转左
        public const int RIGHT_UP = 5;      // 右转上
        public const int DOWN_RIGHT = 6;    // 下转右
        public const int LEFT_DOWN = 7;     // 左转下

        // 顺时针
        public const int LEFT_UP = 8;       // 左转上
        public const int UP_RIGHT = 9;      // 上转右
        public const int RIGHT_DOWN = 10;   // 右转下
        public const int DOWN_LEFT = 11;    // 下转左

        // T型
        public const int T_TOP = 12;        // T型向上
        public const int T_RIGHT = 13;      // T型向右
        public const int T_DOWN = 14;       // T型向下
        public const int T_LEFT  = 15;      // T型向左

        public const int HORIZONTAL = 16;   // 水平
        public const int VERTICAL = 17;     // 垂直
        public const int SURROUND = 18;     // 四周被包围
        public const int ISOLATED = 19;     // 四周被孤立

        private static string[] names = new string[] {
            "UP",
            "RIGHT",
            "DOWN",
            "LEFT",

            "UP_LEFT",
            "RIGHT_UP",
            "DOWN_RIGHT",
            "LEFT_DOWN",

            "LEFT_UP",
            "UP_RIGHT",
            "RIGHT_DOWN",
            "DOWN_LEFT",

            "T_TOP",
            "T_RIGHT",
            "T_DOWN",
            "T_LEFT",

            "HORIZONTAL",
            "VERTICAL",
            "SURROUND",
            "ISOLATED"
        };

        private static Dictionary<string, int> values = new Dictionary<string, int>() {
            { "UP", UP },
            { "RIGHT", RIGHT },
            { "DOWN", DOWN },
            { "LEFT", LEFT },

            { "UP_LEFT", UP_LEFT },
            { "RIGHT_UP", RIGHT_UP },
            { "DOWN_RIGHT", DOWN_RIGHT },
            { "LEFT_DOWN", LEFT_DOWN },

            { "LEFT_UP", LEFT_UP },
            { "UP_RIGHT", UP_RIGHT },
            { "RIGHT_DOWN", RIGHT_DOWN },
            { "DOWN_LEFT", DOWN_LEFT },

            { "T_TOP", T_TOP },
            { "T_RIGHT", T_RIGHT },
            { "T_DOWN", T_DOWN },
            { "T_LEFT", T_LEFT },

            { "HORIZONTAL", HORIZONTAL },
            { "VERTICAL", VERTICAL },
            { "SURROUND", SURROUND },
            { "ISOLATED", ISOLATED }
        };

        /// <summary>
        /// 两个垂直/水平方向是否相反
        /// </summary>
        /// <param name="directionA"></param>
        /// <param name="directionB"></param>
        /// <returns></returns>
        public static bool IsOpposite(int directionA, int directionB) {
            return (directionA == UP && directionB == DOWN)
                || (directionA == DOWN && directionB == UP)
                || (directionA == LEFT && directionB == RIGHT)
                || (directionA == RIGHT && directionB == LEFT)

                || (directionA == T_TOP && directionB == T_DOWN)
                || (directionA == T_DOWN && directionB == T_TOP)
                || (directionA == T_LEFT && directionB == T_RIGHT)
                || (directionA == T_RIGHT && directionB == T_LEFT);
        }

        public static int GetOppsite(int direction) {
            if (direction >= UP && direction <= LEFT) {
                direction += 4;
                direction %= 4;
            }
            // TODO
            return direction;
        }

        /// <summary>
        /// 顺时针/逆时针旋转90度
        /// </summary>
        /// <param name="direction"></param>
        /// <param name="clockwise"></param>
        /// <returns></returns>
        public static int Rotate90(int direction, bool clockwise = true) {
            if(direction >= UP && direction <= LEFT) {
                direction = direction + (clockwise ? 1 : -1);
                direction %= 4;
            }
            else if (direction >= UP_LEFT && direction <= LEFT_DOWN) {
                direction = direction + (clockwise ? 1 : -1);
                direction %= 4;
                direction += 4;
            }
            else if (direction >= T_TOP && direction <= T_LEFT) {
                direction = direction + (clockwise ? 1 : -1);
                direction %= 4;
                direction += 12;
            }
            else if (direction >= LEFT_UP && direction <= DOWN_LEFT) {
                direction = direction + (clockwise ? 1 : -1);
                direction %= 4;
                direction += 8;
            }
            return direction;
        }

        /// <summary>
        /// 是否垂直
        /// </summary>
        /// <param name="dirA"></param>
        /// <param name="dirB"></param>
        /// <returns></returns>
        public static bool IsPerpendicular(int dirA, int dirB) {
            if (dirA >= UP && dirA <= LEFT && dirB >= UP && dirB <= LEFT) {
                return (dirA + 1) % 4 == dirB || (dirA - 1) % 4 == dirB;
            }
            else if (dirA >= UP_LEFT && dirA <= LEFT_DOWN && dirB >= UP_LEFT && dirB <= LEFT_DOWN) {
                return (dirA + 1) % 4 + 4 == dirB || (dirA - 1) % 4 + 4 == dirB;
            }
            else if (dirA >= LEFT_UP && dirA <= DOWN_LEFT && dirB >= LEFT_UP && dirB <= DOWN_LEFT) {
                return (dirA + 1) % 4 + 8 == dirB || (dirA - 1) % 4 + 8 == dirB;
            }
            else if (dirA >= T_TOP && dirA <= T_LEFT && dirB >= T_TOP && dirB <= T_LEFT) {
                return (dirA + 1) % 4 + 12 == dirB || (dirA - 1) % 4 + 12 == dirB;
            }
            return false;
        }

        public static bool IsHorizontal(int direction) {
            return direction == LEFT || direction == RIGHT || direction == HORIZONTAL;
        }

        public static bool IsVertical(int direction) {
            return direction == UP || direction == DOWN || direction == VERTICAL;
        }

        public static string ToString(int direction) {
            return direction >= 0 && direction < names.Length ? names[direction] : NONE.ToString();
        }

        public static int ValueOf(string direction) {
            if(values.TryGetValue(direction.ToUpper(), out int value)) {
                return value;
            }
            return NONE;
        }

        

    }

}
